﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using CDSB.Indicators.Presenter;
using CDSB.Indicators.Model;
using CDSB.Indicators.Enum;
using System.Threading;

namespace CDSB.Indicators.View
{
    public partial class Form1 : Form,ITFSPerformanceIndicator
    {
        #region Constantes
        
        private const string CONFIGURACAO = "Contabilizando Número de Check-Ins Realizados no Período.";
        private const string CHANGEREQUEST = "Contabilizando Número de Change Request Abertas no Período.";
        private const string WORKITEMSPERIODO = "Contabilizando Número Total de WorkItens no Período.";
        private const string PONTUALIDADE = "Gerando Indicador de Pontualidade.";
        private const string BUGSPORCENARIO = "Agrupando Bugs por Cenário.";
        private const string FABRICASOFTWARE = "Gerando Lista de Fábricas de Software.";
        
        private const string FINISHEDMESSAGE = "Concluído";

        #endregion


        delegate void SetTextCallback(IComponent target, string text);
        delegate void SetBindCallback(DataGridView target, Object qualityIndicator);
        delegate void SetButtonVisibleCallback(Button target, bool visible);

        TFSPerformanceIndicator Presenter;
        DateTime DataIni;
        DateTime DataFim;
        Thread trd;

        public Form1()
        {
            InitializeComponent();
            CarregarPeriodoPadrao();
            Presenter = new TFSPerformanceIndicator(this);
        }

        #region ITFSPerformanceIndicator Members

        public void ShowTaskFactoryUnnkow(string tasksId)
        {
            if (this.txtTasksSemFabrica.InvokeRequired)
            {
                SetTextCallback TextDelegate = new SetTextCallback(SetStatus);
                this.Invoke(TextDelegate, new object[] { this.txtTasksSemFabrica, tasksId });
                TextDelegate = null;
            }
            else
            {
                this.txtTasksSemFabrica.Text = tasksId;
            }
        }

        public void ShowChangeSetIndicator(List<CDSB.Indicators.Model.CDSBChangeset> changesets)
        {
            string Checkins = (from changeset in changesets where changeset.ChangeType == ChangeType.Checkin select changeset).Count().ToString();
            string Merges = (from changeset in changesets where changeset.ChangeType == ChangeType.Merge select changeset).Count().ToString();
            
            if (this.txtNumCheckIn.InvokeRequired || this.txtNumMerge.InvokeRequired)
            {
                SetTextCallback TextDelegate = new SetTextCallback(SetStatus);
                this.Invoke(TextDelegate, new object[] { this.txtNumCheckIn, Checkins });
                this.Invoke(TextDelegate, new object[] { this.txtNumMerge, Merges });
                TextDelegate = null;
            }
            else
            {
                this.txtNumCheckIn.Text = Checkins;
                this.txtNumMerge.Text = Merges;
            }
        }

        public void ShowWorkItemsWithoutScenario(string tasks, string bugs)
        {
            if (this.txtTasksSemCenario.InvokeRequired)
            {
                SetTextCallback TextDelegate = new SetTextCallback(SetStatus);
                this.Invoke(TextDelegate, new object[] { this.txtTasksSemCenario, tasks });
                this.Invoke(TextDelegate, new object[] { this.txtBugsSemCenario, bugs });
                TextDelegate = null;
            }
            else
            {
                this.txtTasksSemCenario.Text = tasks;
                this.txtBugsSemCenario.Text = bugs;
            }
        }

        public void ShowInternalExternalTasks(string InternalFactory,string ExternalFactory)
        {
            if (this.txtTasksSemCenario.InvokeRequired)
            {
                SetTextCallback TextInternalDelegate = new SetTextCallback(SetStatus);
                SetTextCallback TextExternalDelegate = new SetTextCallback(SetStatus);
                this.Invoke(TextInternalDelegate, new object[] { this.txtTasksInternas, InternalFactory });
                this.Invoke(TextExternalDelegate, new object[] { this.txtTasksExternas, ExternalFactory });
                TextInternalDelegate = null;
                TextExternalDelegate = null;
            }
            else
            {
                this.txtTasksInternas.Text = InternalFactory;
                this.txtTasksExternas.Text = ExternalFactory;
            }
        }

        public void ShowChangeRequestIndicator(List<CDSBWorkItem> Changerequestlist) 
        {
            if (this.statusBar.InvokeRequired)
            {
                SetTextCallback TextDelegate = new SetTextCallback(SetStatus);
                this.Invoke(TextDelegate, new object[] { this.txtChangeRequest, Changerequestlist.Count.ToString() });
                TextDelegate = null;
            }
            else
            {
                this.txtChangeRequest.Text = Changerequestlist.Count.ToString();
            }
        }

        public void ShowTotalWorkItemsIndicator(int workItemsindicator) 
        {
            if (this.txtQntWorkItems.InvokeRequired)
            {
                SetTextCallback TextDelegate = new SetTextCallback(SetStatus);
                this.Invoke(TextDelegate, new object[] { this.txtQntWorkItems, workItemsindicator.ToString()});
                TextDelegate = null;
            }
            else
            {
                this.txtQntWorkItems.Text = txtQntWorkItems.ToString();
            }   
        }

        public void ShowGeneratePunctualityIndicator(CDSBPunctualityIndicator punctualityIndicator) 
        {
            if (this.txtTasksOnDate.InvokeRequired)
            {
                SetTextCallback TextDelegate = new SetTextCallback(SetStatus);
                this.Invoke(TextDelegate, new object[] { this.txtTotalTasks, punctualityIndicator.TotalTasks.ToString() });
                this.Invoke(TextDelegate, new object[] { this.txtTasksOnDate , punctualityIndicator.OnDate.ToString()});
                this.Invoke(TextDelegate, new object[] { this.txtTasksOnDatePercent, punctualityIndicator.GetOnDatePercent().ToString() + "%" });
                this.Invoke(TextDelegate, new object[] { this.txtTasksOutOfDate, punctualityIndicator.OutOfDate.ToString()});
                this.Invoke(TextDelegate, new object[] { this.txtTasksOutOfDatePercent, punctualityIndicator.GetOutOfDatePercent().ToString()+"%" });
                this.Invoke(TextDelegate, new object[] { this.txtAllTaskPercent, "100%" }); 
                TextDelegate = null;
            }
            else
            {
                this.txtQntWorkItems.Text = txtQntWorkItems.ToString();
            }   
        }

        public void ShowCodeReviewPercent(decimal codeReviewPercent)
        {
            if (this.txtCodeReview.InvokeRequired)
            {
                SetTextCallback TextDelegate = new SetTextCallback(SetStatus);

                this.Invoke(TextDelegate, new object[] { this.txtCodeReview , codeReviewPercent.ToString() + "%" });

                TextDelegate = null;
            }
            else
            {
                this.txtCodeReview.Text = codeReviewPercent.ToString() + "%";
            }
        }

        public void ShowIndicatorGeneratingFactor(List<CDSBBugGeneratorIndicator> GeneratingFactor)
        {
            if (this.dtgFatorGerador.InvokeRequired)
            {
                SetBindCallback BindDelegate = new SetBindCallback(SetBind);

                this.Invoke(BindDelegate, new object[] { this.dtgFatorGerador, GeneratingFactor });

                BindDelegate = null;
            }
            else
            {
                this.dtgFatorGerador.DataSource = GeneratingFactor;
            }
        }

        public void ShowQualityIndicator(List<CDSBQualityIndicator> qualityIndicator) 
        {
            if (this.dtgIndiceFabril.InvokeRequired)
            {
                SetBindCallback BindDelegate = new SetBindCallback(SetBind);

                this.Invoke(BindDelegate, new object[] { this.dtgQualidade, qualityIndicator });

                BindDelegate = null;
            }
            else
            {
                this.dtgIndiceFabril.DataSource = qualityIndicator;
            } 
        }

        public void ShowCodeProviderIndicator(List<CDSBFactoryIndicator> ProviderIndicatorList) 
        {
            if (this.dtgIndiceFabril.InvokeRequired)
            {
                SetBindCallback BindDelegate = new SetBindCallback(SetBind);

                this.Invoke(BindDelegate, new object[] { this.dtgIndiceFabril, ProviderIndicatorList });

                BindDelegate = null;
            }
            else
            {
                this.dtgIndiceFabril.DataSource = ProviderIndicatorList;
            }    
        }

        public void ShowStatus(StepMessage step)
        {
            if (this.statusBar.InvokeRequired)
            {
                SetTextCallback TextDelegate = new SetTextCallback(SetStatus);
                this.Invoke(TextDelegate, new object[] { this.statusBarLabelText, this.getStepMassage(step) });
                TextDelegate = null;
            }
            else 
            {
                this.statusBar.Text = this.getStepMassage(step);
            }
        }

        private string getStepMassage(StepMessage step)
        {
            switch (step)
            {
                case StepMessage.Punctuality:
                    return PONTUALIDADE;
                case StepMessage.Configuration:
                    return CONFIGURACAO;
                case StepMessage.Changerequest:
                    return CHANGEREQUEST;
                case StepMessage.Period:
                    return WORKITEMSPERIODO;
                case StepMessage.ScenarioList:
                    return string.Empty;
                case StepMessage.ScenarioNumber:
                    return string.Empty;
                case StepMessage.ScenariosInProjects:
                    return string.Empty;
                case StepMessage.Quality:
                    return BUGSPORCENARIO;
                case StepMessage.CodeReview:
                    return string.Empty;
                case StepMessage.CodeProvider:
                    return FABRICASOFTWARE;
                case StepMessage.Finished:
                    return FINISHEDMESSAGE;
                default:
                    return string.Empty;
            }
        }

        private void SetStatus(IComponent target, string text)
        {
            string ComponentType = target.GetType().Name.ToLower();

            switch (ComponentType)
            {
                case "textbox":
                    ((TextBox)target).Text = text;
                    break;
                case "toolstripstatuslabel":
                    ((ToolStripStatusLabel)target).Text = text;
                    break;
            }
        }

        private void SetBind(DataGridView target, Object qualityIndicator) 
        {
            target.DataSource = qualityIndicator;
        }

        #endregion

        private void btnGerarIndicadores_Click(object sender, EventArgs e)
        {
            if (ValidarDatas())
            {
                trd = new Thread(new ThreadStart(callIndicadores));
                trd.IsBackground = true;
                trd.Start();
                this.btnPararGeracao.Visible = true;
                this.btnGerarIndicadores.Visible = false;
            }
        }

        private void btnPararGeracao_Click(object sender, EventArgs e)
        {
            try
            {
                trd.Abort();
                this.btnGerarIndicadores.Visible = true;
                this.btnPararGeracao.Visible = false;
            }
            catch 
            {
                MessageBox.Show("Processo de Geração Cancelado pelo Usuário!", "Gerador de Indicadores", MessageBoxButtons.OK, MessageBoxIcon.Information);
                this.statusBarLabelText.Text = "Pronto";
            }
        }

        public void NotifyFinalProcess(bool hasErrors)
        {
            if (hasErrors)
            {
                MessageBox.Show("Atenção! " + Environment.NewLine + "Processo de Geração dos Indicadores Concluído com Erros! Por Favor, averigue workitems listados os campos em amarelo e gere novamente os indicadores.", "Gerador de Indicadores", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            else 
            {
                MessageBox.Show("Processo de Geração dos Indicadores Concluído com Sucesso!.", "Gerador de Indicadores", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }

            if (this.statusBar.InvokeRequired)
            {
                SetButtonVisibleCallback ButtonDelegate = new SetButtonVisibleCallback(SetVisible);
                this.Invoke(ButtonDelegate, new object[] { this.btnGerarIndicadores, true});
                this.Invoke(ButtonDelegate, new object[] { this.btnPararGeracao, false});
                ButtonDelegate = null;
            }
            else 
            {
                this.btnGerarIndicadores.Visible = true;
                this.btnPararGeracao.Visible = false;                
            }
        }

        public void SetVisible(Button target, bool visible) 
        {
            target.Visible = visible;
        }

        private void callIndicadores() 
        {
            this.Presenter.GeneratePerformanceIndicators(this.DataIni, this.DataFim,chkPontualidade.Checked,chkConfiguracao.Checked,chkChangeRequest.Checked, chkHorasPeriodo.Checked);
        }

        private bool ValidarDatas() 
        {
            bool dataValida = false;
            
            try
            {
                string[] spliDataIni = txtDataIni.Text.Split('/');
                string[] spliDataFim = txtDataFim.Text.Split('/');

                DataIni = new DateTime(Convert.ToInt32(spliDataIni[2]), Convert.ToInt32(spliDataIni[1]), Convert.ToInt32(spliDataIni[0]));
                DataFim = new DateTime(Convert.ToInt32(spliDataFim[2]), Convert.ToInt32(spliDataFim[1]), Convert.ToInt32(spliDataFim[0]));

                if (DataIni > DataFim)
                {
                    MessageBox.Show("O Período Informado está inválido!", "Gerador de Indicadores", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    dataValida = false;
                }
                else
                {
                    dataValida = true;
                }
            }
            catch
            {
                MessageBox.Show("Ambas ou uma das datas informada é inválida!", "Gerador de Indicadores", MessageBoxButtons.OK, MessageBoxIcon.Error);
                dataValida = false;
            }

            return dataValida;
        }

        private void CarregarPeriodoPadrao() 
        {
            string D1 = "{0}/{1}/{2}";
            string D2 = "{0}/{1}/{2}";

            this.txtDataIni.Text = String.Format(D1, 1, DateTime.Now.Month, DateTime.Now.Year);
            this.txtDataFim.Text = String.Format(D2, DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month),DateTime.Now.Month, DateTime.Now.Year);
        }
    }
}
